﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.AxHost;

namespace Scrat.Core.Server
{

    public struct State
    {
        public TcpListener Server;
        public Stream FStream;

        public State(TcpListener server, Stream fStream)
        {
            Server = server;
            FStream = fStream;
        }
    }

    public class TCPFileStreamServer
    {
        private static TCPFileStreamServer _instance;
        
        private TcpListener _tcpListener;
        private Stream _stream;
        private State _state;

        private TCPFileStreamServer(IPAddress ipAddress, int port)
        {
            _tcpListener = new TcpListener(new IPEndPoint(ipAddress, port));
            
        }

        public static TCPFileStreamServer GetInstance(IPAddress ipAddress, int port)
        {
            if (_instance == null)
            { 
                _instance = new TCPFileStreamServer(ipAddress, port);
            }
            return _instance;
        }

        
        public void Start(Stream stream)
        {
            _stream = stream;
            _tcpListener?.Start();

            _state = new State(_tcpListener, _stream);


            _tcpListener.BeginAcceptTcpClient(new AsyncCallback(OnClientConnected), _state);
        }

        private async void OnClientConnected(IAsyncResult ar)
        {
            if (ar.IsCompleted)
            {
                var state = (State)ar.AsyncState;

                var fStream = state.FStream;
                var server = state.Server;

                TcpClient client = null;
                try
                {
                    client = server.EndAcceptTcpClient(ar);

                    await fStream.CopyToAsync(client.GetStream());
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.StackTrace.ToString());
                }
                finally
                {
                    _tcpListener.BeginAcceptTcpClient(new AsyncCallback(OnClientConnected), _state);
                }
            }
        }

        public void Stop()
        {
            try
            {
                _tcpListener?.Stop();
                _stream?.Close();
            }
            finally
            {
                _tcpListener = null;
                _instance = null;
                _stream = null;
            }
        }
    }
}
